﻿using System;
using System.Collections.Generic;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;

namespace AsyncLoggers.EnterpriseLibrary
{
    /// <summary>
    /// Asynchronous LogWriter implementation.
    /// </summary>
    public class AsyncLogWriter : LogWriter
    {
        private readonly LogWriter _wrappedLogWriter;
        private readonly CommandProcessor _commandProcessor = new CommandProcessor();

        /// <summary>
        /// Constructs new instance of Asynchronous LogWriter.
        /// </summary>
        public AsyncLogWriter(LogWriter wrappedLogWriter)
        {
            if (wrappedLogWriter == null) throw new ArgumentNullException("wrappedLogWriter");

            _wrappedLogWriter = wrappedLogWriter;
        }

        /// <summary>
        /// Returns the filter of type <typeparamref name="T"/>.
        /// </summary>
        /// <typeparam name="T">The type of filter requiered.</typeparam>
        /// <returns>
        /// The instance of <typeparamref name="T"/> in the filters collection, or <see langword="null"/> 
        ///             if there is no such instance.
        /// </returns>
        public override T GetFilter<T>()
        {
            return _wrappedLogWriter.GetFilter<T>();
        }

        /// <summary>
        /// Returns the filter of type <typeparamref name="T"/> named <paramref name="name"/>.
        /// </summary>
        /// <typeparam name="T">The type of filter required.</typeparam><param name="name">The name of the filter required.</param>
        /// <returns>
        /// The instance of <typeparamref name="T"/> named <paramref name="name"/> in 
        ///             the filters collection, or <see langword="null"/> if there is no such instance.
        /// </returns>
        public override T GetFilter<T>(string name)
        {
            return _wrappedLogWriter.GetFilter<T>(name);
        }

        /// <summary>
        /// Returns the filter named <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the filter required.</param>
        /// <returns>
        /// The filter named <paramref name="name"/> in 
        ///             the filters collection, or <see langword="null"/> if there is no such filter.
        /// </returns>
        public override ILogFilter GetFilter(string name)
        {
            return _wrappedLogWriter.GetFilter(name);
        }

        /// <summary>
        /// Gets a list of <see cref="T:Microsoft.Practices.EnterpriseLibrary.Logging.LogSource"/> objects for the log entry.
        /// </summary>
        /// <param name="logEntry">The <see cref="T:Microsoft.Practices.EnterpriseLibrary.Logging.LogEntry"/> to get the matching trace sources.</param>
        /// <returns>
        /// A collection of <see cref="T:Microsoft.Practices.EnterpriseLibrary.Logging.LogSource"/> objects.
        /// </returns>
        public override IEnumerable<LogSource> GetMatchingTraceSources(LogEntry logEntry)
        {
            return _wrappedLogWriter.GetMatchingTraceSources(logEntry);
        }

        /// <summary>
        /// Queries whether logging is enabled.
        /// </summary>
        /// <returns>
        /// <b>true</b> if logging is enabled.
        /// </returns>
        public override bool IsLoggingEnabled()
        {
            return _wrappedLogWriter.IsLoggingEnabled();
        }

        /// <summary>
        /// Queries whether tracing is enabled.
        /// </summary>
        /// <returns>
        /// <b>true</b> if tracing is enabled.
        /// </returns>
        public override bool IsTracingEnabled()
        {
            return _wrappedLogWriter.IsTracingEnabled();
        }

        /// <summary>
        /// Queries whether a <see cref="T:Microsoft.Practices.EnterpriseLibrary.Logging.LogEntry"/> shold be logged.
        /// </summary>
        /// <param name="log">The log entry to check.</param>
        /// <returns>
        /// <b>true</b> if the entry should be logged.
        /// </returns>
        public override bool ShouldLog(LogEntry log)
        {
            if (log == null) throw new ArgumentNullException("log");

            return _wrappedLogWriter.ShouldLog(log);
        }

        /// <summary>
        /// Writes a new log entry as defined in the <see cref="T:Microsoft.Practices.EnterpriseLibrary.Logging.LogEntry"/> parameter.
        /// </summary>
        /// <param name="log">Log entry object to write.</param>
        public override void Write(LogEntry log)
        {
            if (log == null) throw new ArgumentNullException("log");

            _commandProcessor.QueueCommand(new ActionCommand(() => _wrappedLogWriter.Write(log)));
        }

        /// <summary>
        /// Gets the <see cref="T:Microsoft.Practices.EnterpriseLibrary.Logging.LogSource"/> mappings available for the <see cref="T:Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter"/>.
        /// </summary>
        public override IDictionary<string, LogSource> TraceSources
        {
            get
            {
                return _wrappedLogWriter.TraceSources;
            }
        }
    }
}